package com.opennetexam.manager.bussinessservice;

import com.opennetexam.manager.common.CacheKey;
import com.opennetexam.manager.facecompare.FaceCompareByFile;
import com.opennetexam.manager.mapper.*;
import com.opennetexam.manager.common.OperationResult;
import com.opennetexam.manager.common.RoomControl;
import com.opennetexam.manager.databasemodel.*;
import com.opennetexam.manager.dto.*;
import com.opennetexam.manager.enums.*;
import com.opennetexam.manager.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.File;
import java.net.UnknownHostException;
import java.util.*;
/**
 * Created by admin on 2017/12/7.
 */
@Service("beforeExamService")
@Transactional(rollbackFor = Exception.class)
public class BeforeExamService {

    @Autowired
    private ExamComputerMapper examComputerMapper;
    @Autowired
    private ExamineeMapper examineeMapper;
    @Autowired
    private ExamMoniterMapper examMoniterMapper;
    @Autowired
    private ExamPlanInfoMapper examPlanInfoMapper;
    @Autowired
    private ExamineeArrangeMapper examineeArrangeMapper;
    @Autowired
    private ExamineeAnswerDetailMapper examineeAnswerDetailMapper;
    @Autowired
    private ExamPaperService examPaperService;
    @Autowired
    private ExamingService examingService;
    @Autowired
    private ExamPhotoService examPhotoService;
    @Autowired
    private FaceCompareByFile faceCompareByFile;
    @Autowired
    private ExamSubjectMapper examSubjectMapper;

    @Value("${FaceCompareSocre}")
    private Double faceCompareSocre;

    /**
     *  根据当前客户端的IP尝试获取座位号
     *  @param hostAddress 当前客户端IP
     * @return
     */
    public Integer getSeatNo(String hostAddress) {
        ExamComputer examComputer = examComputerMapper.findExamComputerByIp(hostAddress);
        return examComputer == null ? 0 : examComputer.getSeatNo();
    }

    /**
     * 准考证号查询考生信息
     * @param examCardNo
     * @return
     */
    public List<Examinee> getExaminees(String examCardNo) {
       return  examineeMapper.findExamineesByCardNo(examCardNo.toUpperCase());
    }

    /**
     * 获取匹配的 考生、计划、监控、编排 数据
     * @param tempExamineeList
     * @return
     */
    public List<ClientLoginModel> getExamClientData(List<Examinee> tempExamineeList) {
        List<ClientLoginModel> clientLoginData = new ArrayList<>();
        //获取当前时间
        String serviceTime = DateUtil.convertEncryptDateToString(new Date());
        //已生成试卷
        Integer testPaperCreated = ExamPlanSysState.TestPaperCreated.getPrefix();
        //已交卷
        Integer submited = ExamManagerState.Submited.getPrefix();

        for(Examinee tempExaminee : tempExamineeList){
            String examineeId = tempExaminee.getExamineeID();
            String appId = "" ;
            String planId = null;
            String subjectId = null;
            String examCardNo = "";
            List<Examinee> examineeList = examineeMapper.findExamClientExaminee(TableNameType.EXAMINEE.getDisplay(),examineeId, serviceTime,
                    testPaperCreated, submited,appId,planId,subjectId,examCardNo);
            List<ExamineeArrange> examineeArrangeList = examineeMapper.findExamClientExamineeArrange(TableNameType.EXAMINEEARRANGE.getDisplay(),examineeId, serviceTime,
                    testPaperCreated, submited,appId,planId,subjectId,examCardNo);
            List<ExamingMonitor> examingMonitorList = examineeMapper.findExamClientExamingMonitor(TableNameType.EXAMINGMONITOR.getDisplay(),examineeId, serviceTime,
                    testPaperCreated, submited,appId,planId,subjectId,examCardNo);
            List<ExamPlanInfo> examPlanInfoList = examineeMapper.findExamClientExamPlanInfo(TableNameType.EXAMPLANINFO.getDisplay(),examineeId, serviceTime,
                    testPaperCreated, submited,appId,planId,subjectId,examCardNo);
            List<ExamRoom> examRoomList = examineeMapper.findExamClientExamRoom(TableNameType.EXAMROOM.getDisplay(),examineeId, serviceTime,
                    testPaperCreated, submited,appId,planId,subjectId,examCardNo);
            List<ExamScenes> examScenesList = examineeMapper.findExamClientExamScenes(TableNameType.EXAMSCENES.getDisplay(),examineeId, serviceTime,
                    testPaperCreated, submited,appId,planId,subjectId,examCardNo);
            List<ExamSite> examSiteList = examineeMapper.findExamClientExamSite(TableNameType.EXAMSITE.getDisplay(),examineeId, serviceTime,
                    testPaperCreated, submited,appId,planId,subjectId,examCardNo);
            List<ExamSubject> examSubjectList = examineeMapper.findExamClientExamSubject(TableNameType.EXAMSUBJECT.getDisplay(),examineeId, serviceTime,
                    testPaperCreated, submited,appId,planId,subjectId,examCardNo);


            if(examineeList != null && !examineeList.isEmpty()){
                for ( int i = 0 ; i < examineeList.size() ; i++){
                    ClientLoginModel addClientLoginModel = new ClientLoginModel();
                    addClientLoginModel.setExaminee(examineeList.get(i));
                    addClientLoginModel.setExamArrange(examineeArrangeList.get(i));
                    addClientLoginModel.setExamMonitor(examingMonitorList.get(i));
                    addClientLoginModel.setExamPlan(examPlanInfoList.get(i));
                    addClientLoginModel.setExamRoom(examRoomList.get(i));
                    addClientLoginModel.setExamScenes(examScenesList.get(i));
                    addClientLoginModel.setExamSite(examSiteList.get(i));
                    addClientLoginModel.setExamSubject(examSubjectList.get(i));
                    clientLoginData.add(addClientLoginModel);
                }
            }
        }
        return  clientLoginData;
    }

    /**
     * 更新考试登录相关的状态和时间
     * @param appId  主办方标识
     * @param examPlanInfoId  计划标识
     * @param examSubjectId  科目标识
     * @param examineeId  考生标识'
     * @param examManagerState 考试状态 0:未开考
     * @throws Exception
     */
    public void updateMonitorForLogin (String appId, String examPlanInfoId, String examSubjectId, String examineeId,Integer examManagerState){

        ExamingMonitor monitor = examMoniterMapper.findDisciplineExamingMonitors(appId,examPlanInfoId,examSubjectId,examineeId,examManagerState);
        if(!StringUtils.isEmpty(monitor)){
            monitor.setSysState(ExamManagerState.Login.getPrefix().shortValue());
            monitor.setLoginTime(DateUtil.convertEncryptDateToString(new Date()));
            examMoniterMapper.updateExamingMoniter(monitor);
        }
    }


    /**
     * 获取科目列表（正式和模拟）
     * 根据考生编号获取考生随到随考类型考试列表和完成状态
     * @param token key
     * @param examPlanType   0：正式  1：模拟
     * @return
     */
    public List<ExamineePlanInfo> getAnyTimeExam(String token, Integer examPlanType) {
        //获取缓存数据
         ClientLoginModel clientLoginModel = getEhCacheValue(token);
        Examinee examinee = clientLoginModel.getExaminee();

        //根据考生编号获取考生随到随考类型考试列表和完成状态
        String appId = examinee.getAppID();
        String examineeId = examinee.getExamineeID();

        PublicHelper.checkArgument(appId, "appId");
        PublicHelper.checkArgument(examineeId, "examineeId");

        //可能有两个人
        Examinee examOne = examineeMapper.findFirstExamineesByExamineeId(examineeId);

        //考生考试管理状态  3：已交卷
        Integer submited = ExamManagerState.Submited.getPrefix();
        //考试计划系统状态  6:已生成试卷
        Integer testPaperCreated = ExamPlanSysState.TestPaperCreated.getPrefix();

        if(ExamPlanApplicationRange.Formal.getPrefix().equals(examPlanType)){
            //考试模式  3：随考
            Integer freeExam = ExamMode.freeExam.getPrefix();
            List<ExamPlanInfo> examPlanInfos = examPlanInfoMapper.findExamPlanInfoByAppIdAndModeAndType(appId,freeExam,examPlanType);

            if(examPlanInfos == null || examPlanInfos.isEmpty()){
                return new ArrayList<>();
            }else {
                //查询当前时间段符合的随考模式数据
                String timeNow = DateUtil.convertEncryptDateToString(new Date());
                //examPlanInfoIds
                List<String> examPlanInfoIds = new ArrayList<>();
                for (ExamPlanInfo examPlanInfo : examPlanInfos) {
                    examPlanInfoIds.add(examPlanInfo.getExamPlanInfoID());
                }
                //查询考生信息
                List<Examinee> examineeList = examineeMapper.findExamineesByCardNo(examOne.getExamCardNo());
                //examineeIds
                List<String> examineeIds = new ArrayList<>();
                for (Examinee forexaminee : examineeList){
                    examineeIds.add(forexaminee.getExamineeID());
                }

                return examPlanInfoMapper.findExamineePlanInfoList(examPlanInfoIds,examineeIds,submited,testPaperCreated,timeNow);
            }
        }else {
            List<ExamPlanInfo> examPlanInfos = examPlanInfoMapper.findExamPlanInfoByAppIdAndType(appId,examPlanType);
            if(examPlanInfos == null || examPlanInfos.isEmpty()){
                return new ArrayList<>();
            }else {

                //examPlanInfoIds
                List<String> examPlanInfoIds = new ArrayList<>();
                for (ExamPlanInfo examPlanInfo : examPlanInfos) {
                    examPlanInfoIds.add(examPlanInfo.getExamPlanInfoID());
                }
                //查询考生信息
                List<Examinee> examineeList = examineeMapper.findExamineesByCardNo(examOne.getExamCardNo());
                //examineeIds
                List<String> examineeIds = new ArrayList<>();
                for (Examinee forexaminee : examineeList){
                    examineeIds.add(forexaminee.getExamineeID());
                }

                return examPlanInfoMapper.findExamineePlanInfoList(examPlanInfoIds,examineeIds,submited,testPaperCreated,"");
            }

        }
    }

    /**
     * 解锁验证证件号是否正确
     * @param examCardNo  准考证号
     * @param idCardNo 证件号码
     * @return
     */
    public boolean checkIdCard(String examCardNo, String idCardNo) {
        boolean judgeCardNo = true;
        List<Examinee> examineeList = examineeMapper.findExamineesByCardNoAndCertificateNo(examCardNo,idCardNo);
        if(examineeList == null || examineeList.isEmpty()){
            judgeCardNo = false;
        }
        return judgeCardNo;

    }

    /**
     * 判断科目是否签到
     * @param token key
     * @param appId  主办方标识
     * @param planId  计划标识
     * @param subjectId 科目标识
     * @return
     */
    public boolean isSignSubject(String token, String appId, String planId, String subjectId) {

        PublicHelper.checkArgument(appId, "appId");
        PublicHelper.checkArgument(planId, "planId");
        PublicHelper.checkArgument(subjectId, "subjectId");

        //获取缓存数据
        ClientLoginModel clientLoginModel = getEhCacheValue(token);
        Examinee examinee = clientLoginModel.getExaminee();

        String examineeId = examinee.getExamineeID();
        //查询考试计划
        ExamPlanInfo examPlanInfo = examPlanInfoMapper.getExamPlanInfoBySysState(appId, planId,ExamPlanSysState.TestPaperCreated.getPrefix());
        if(examPlanInfo == null){
            return  false;
        }else if(examPlanInfo.getRequiredSignIn() != 1 ){
            //不需要签到  requiredSignIn 1：需要签到
            return true;
        }

        //未签到
        Integer unSignIn = SignInType.UnSignIn.getPrefix();
        ExamingMonitor examingMonitors = examMoniterMapper.findExamingMonitorsBySignStatus(appId, planId, subjectId, examineeId, unSignIn);
        if(examingMonitors == null){
            return  false;
        }

        if(ExamMode.freeExam.getPrefix().equals(examPlanInfo.getExamMode())){

            //当前时间戳
            long nowTime = System.currentTimeMillis();
            //考试当天开始时间
            long beginTime = DateUtil.getDateStartTime(nowTime);
            //考试当天结束时间
            long endTime = DateUtil.getDateEndTime(nowTime);

            long idCardTime = DateUtil.convertStringToDate(examingMonitors.getiDCardTime()).getTime();
            if (!(idCardTime >= beginTime && idCardTime < endTime)){
                return false;
            }
        }

        return true;
    }

    /**
     * 非正式统考 获取匹配的 考生、计划、监控、编排 数据
     * @param token  key
     * @param appId  主办方标识
     * @param planId  计划标识
     * @param subjectId 科目标识
     * @return
     */
    public DownloadPaperVo getMorkUnifiedExam(String token,String appId, String planId, String subjectId,String hostAddress){
        //获取缓存数据
        ClientLoginModel clientLoginModel = getEhCacheValue(token);
        Examinee examinee = clientLoginModel.getExaminee();

        //准考证号
        String examCardNo = examinee.getExamCardNo().toLowerCase();
        //获取服务器时间
        String serviceTime = DateUtil.convertEncryptDateToString(new Date());
        //已生成试卷
        Integer testPaperCreated = ExamPlanSysState.TestPaperCreated.getPrefix();
        //已交卷
        Integer submited = ExamManagerState.Submited.getPrefix();
        String examineeId = null;

        List<Examinee> examineeList = examineeMapper.findExamClientExaminee(TableNameType.EXAMINEE.getDisplay(),examineeId, serviceTime,
                testPaperCreated, submited,appId,planId,subjectId,examCardNo);
        List<ExamineeArrange> examineeArrangeList = examineeMapper.findExamClientExamineeArrange(TableNameType.EXAMINEEARRANGE.getDisplay(),examineeId, serviceTime,
                testPaperCreated, submited,appId,planId,subjectId,examCardNo);
        List<ExamingMonitor> examingMonitorList = examineeMapper.findExamClientExamingMonitor(TableNameType.EXAMINGMONITOR.getDisplay(),examineeId, serviceTime,
                testPaperCreated, submited,appId,planId,subjectId,examCardNo);
        List<ExamPlanInfo> examPlanInfoList = examineeMapper.findExamClientExamPlanInfo(TableNameType.EXAMPLANINFO.getDisplay(),examineeId, serviceTime,
                testPaperCreated, submited,appId,planId,subjectId,examCardNo);
        List<ExamRoom> examRoomList = examineeMapper.findExamClientExamRoom(TableNameType.EXAMROOM.getDisplay(),examineeId, serviceTime,
                testPaperCreated, submited,appId,planId,subjectId,examCardNo);
        List<ExamScenes> examScenesList = examineeMapper.findExamClientExamScenes(TableNameType.EXAMSCENES.getDisplay(),examineeId, serviceTime,
                testPaperCreated, submited,appId,planId,subjectId,examCardNo);
        List<ExamSite> examSiteList = examineeMapper.findExamClientExamSite(TableNameType.EXAMSITE.getDisplay(),examineeId, serviceTime,
                testPaperCreated, submited,appId,planId,subjectId,examCardNo);
        List<ExamSubject> examSubjectList = examineeMapper.findExamClientExamSubject(TableNameType.EXAMSUBJECT.getDisplay(),examineeId, serviceTime,
                testPaperCreated, submited,appId,planId,subjectId,examCardNo);


        if(examineeList != null && !examineeList.isEmpty()){
            clientLoginModel.setExaminee(examineeList.get(0));
            clientLoginModel.setExamArrange(examineeArrangeList.get(0));
            clientLoginModel.setExamMonitor(examingMonitorList.get(0));
            clientLoginModel.setExamPlan(examPlanInfoList.get(0));
            clientLoginModel.setExamRoom(examRoomList.get(0));
            clientLoginModel.setExamScenes(examScenesList.get(0));
            clientLoginModel.setExamSite(examSiteList.get(0));
            clientLoginModel.setExamSubject(examSubjectList.get(0));
        }

        // 如果是模拟考试，TimeTobegin和 MinExamTime 赋值
        if(clientLoginModel.getExamPlan().getExamPlanType().equals(ExamPlanApplicationRange.Mock.getPrefix().shortValue())){
            clientLoginModel.getExamArrange().setPlanBeginTime(serviceTime);
            clientLoginModel.getExamPlan().setMinExamTime(0);
        }

        // 更新缓存，在这里确认考生唯一性
        clientLoginModel.setExamineePhoto("url");
        clientLoginModel.setUserHostAddress(hostAddress);

        //写入缓存
        if( PatternUtil.getPatternSplit(token,":").size() > 1){
            RedisUtil.setValue(token,GsonUtil.toJson(clientLoginModel),21600);
        }else {
            //ehCacheManager.put(token, GsonUtil.toJson(clientLoginModel));
        }

        // 更新登录状态和时间
        Integer sysState = Integer.valueOf(clientLoginModel.getExamMonitor().getSysState());
        if(ExamManagerState.Discipline.getPrefix().equals(sysState)){
            updateMonitorForLogin(clientLoginModel.getExaminee().getAppID(),
                    clientLoginModel.getExamPlan().getExamPlanInfoID(),
                    clientLoginModel.getExamSubject().getExamSubjectID(),
                    clientLoginModel.getExaminee().getExamineeID(),
                    ExamManagerState.Discipline.getPrefix()
            );
        }

        //获取考试的计划开始时间
        ExamineeArrange examineeArrange = examineeArrangeMapper.findExamBeginTime(clientLoginModel.getExaminee().getExamineeID(),
                clientLoginModel.getExamPlan().getExamPlanInfoID(),clientLoginModel.getExaminee().getAppID(),clientLoginModel.getExamSubject().getExamSubjectID());
        String planBeginTime = examineeArrange.getPlanBeginTime();

        return  getDownloadPaperVo(clientLoginModel,token,planBeginTime,hostAddress);
    }

    public DownloadPaperVo getDownloadPaperVo(ClientLoginModel clientLoginModel, String token, String planBeginTime,String hostAddress){
        //返回vo
        DownloadPaperVo downloadPaperVo = new DownloadPaperVo();
        ExamineeVo examineeVo = new ExamineeVo();
        examineeVo.setExamCardNo(clientLoginModel.getExaminee().getExamCardNo());
        examineeVo.setSeatNo(clientLoginModel.getExamArrange().getSeatNo() == null ? 0 : clientLoginModel.getExamArrange().getSeatNo());
        examineeVo.setSex(SystemSex.Man.getPrefix().equals(clientLoginModel.getExaminee().getSex())
                ? SystemSex.Man.getDisplay() : SystemSex.Woman.getDisplay());
        examineeVo.setStuName(clientLoginModel.getExaminee().getExamineeName());
        examineeVo.setIdCard(clientLoginModel.getExaminee().getCertificateNo());
        examineeVo.setPhotoUrl(clientLoginModel.getExaminee().getPhotoResource());//考生头像图片
        examineeVo.setCertificateType(CertificateType.getcertificateType(clientLoginModel.getExaminee().getCertificateType().intValue()));
        downloadPaperVo.setInfo(examineeVo);
        // 是否跳转须知页面，1跳转0不跳转
        //获取当前时间戳
        long nowTime = System.currentTimeMillis();
        downloadPaperVo.setIfTurnNotice(nowTime < DateUtil.convertStringToDate(planBeginTime).getTime() ? 1 : 0);
        // 是否显示座位号
        downloadPaperVo.setIsShowSeat(getSeatNo(hostAddress));
        //照片显示所需的几个参数
        downloadPaperVo.setAppId(clientLoginModel.getExaminee().getAppID());
        downloadPaperVo.setPlanId(clientLoginModel.getExamArrange().getExamPlanInfoID());
        downloadPaperVo.setScenceId(clientLoginModel.getExamArrange().getExamSceneID());
        downloadPaperVo.setExamineeId(clientLoginModel.getExamArrange().getExamineeID());
        downloadPaperVo.setToken(token);
        return  downloadPaperVo;
    }

    /**
     * 正式统考 获取匹配的 考生、计划、监控、编排 数据
     * @param token
     * @return
     */
    public DownloadPaperVo getFormalUnifiedExam(String token,String appId, String planId, String subjectId,String hostAddress) {
        //获取缓存数据
        ClientLoginModel clientLoginModel = getEhCacheValue(token);
        Examinee examinee = clientLoginModel.getExaminee();
        ExamPlanInfo examPlanInfo = clientLoginModel.getExamPlan();

        ExamSubject subject = examSubjectMapper.examSubjectFirstOrDefault(appId, planId, subjectId);
        clientLoginModel.setExamSubject(subject);
        //获取考试的计划开始时间
        ExamineeArrange examineeArrangeSel = examineeArrangeMapper.findExamBeginTime(examinee.getExamineeID(),
                examPlanInfo.getExamPlanInfoID(),examinee.getAppID(),subject.getExamSubjectID());
        String planBeginTime = examineeArrangeSel.getPlanBeginTime();

        clientLoginModel.setExamArrange(examineeArrangeSel);
        //更新科目缓存
        if( PatternUtil.getPatternSplit(token,":").size() > 1){
            RedisUtil.setValue(token,GsonUtil.toJson(clientLoginModel),21600);
        }

        return  getDownloadPaperVo(clientLoginModel,token,planBeginTime,hostAddress);
    }

    /**
     * 获取考试须知页所需数据
     * @param token
     * @return
     */
    public ExamNoticeVo getExamNoticeResult(String token) {

        ExamNoticeVo examNoticeVo = new  ExamNoticeVo();
        //获取缓存数据
        ClientLoginModel ehCacheValue = getEhCacheValue(token);
        Examinee examinee = ehCacheValue.getExaminee();
        ExamSubject subject = ehCacheValue.getExamSubject();

        examNoticeVo.setNotice(subject.getExamNotice());
        examNoticeVo.setGatherTime(subject.getTimeLimits());
        examNoticeVo.setStuName(examinee.getExamineeName());
        examNoticeVo.setToken(token);
        return examNoticeVo;
    }

    /**
     * 封装考试所需数据
     * @param token
     * @return
     */
    public ExamInfoVo getExam(String token) {
        //返回vo
        ExamInfoVo examInfoVo = new ExamInfoVo();
        //获取缓存数据
        ClientLoginModel ehCacheValue = getEhCacheValue(token);
        Examinee examinee = ehCacheValue.getExaminee();
        ExamPlanInfo examPlanInfo = ehCacheValue.getExamPlan();
        ExamineeArrange examineeArrange = ehCacheValue.getExamArrange();
        ExamSubject subject = ehCacheValue.getExamSubject();

        exExamStateAndTime(examPlanInfo.getAppID(),examPlanInfo.getExamPlanInfoID(),examineeArrange.getExamSubjectID(),examinee.getExamineeID());

        examInfoVo.setSeatByNumberRequired(examPlanInfo.getRequiredSignIn());
        examInfoVo.setTooltipText(ExamPlanApplicationRange.Mock.getPrefix().equals(examPlanInfo.getExamPlanType().intValue())
                ? ExamPlanApplicationRange.Mock.getDisplay() : ExamPlanApplicationRange.Formal.getDisplay());
        examInfoVo.setTitle(subject.getSubjectName());
        examInfoVo.setExamineeSex(examinee.getSex());
        // (机考)照片显示所需的几个参数
        examInfoVo.setAppId(examinee.getAppID());
        examInfoVo.setPlanId(examineeArrange.getExamPlanInfoID());
        examInfoVo.setScenceId(examineeArrange.getExamSceneID());
        examInfoVo.setExamineeId(examinee.getExamineeID());
        examInfoVo.setToken(token);

        //（网考）照片显示路径
        examInfoVo.setExaminerHeadPhotoUrl(examinee.getPhotoResource());
        //（网考）试卷图片显示所需参数
        //  /{examplanid}/{examsiteid}/paper/{subjectcode}/AssessmentItems
        examInfoVo.setExamsiteid(ehCacheValue.getExamPlan().getExamSiteID());
        examInfoVo.setSubjectcode(subject.getSubjectCode());

        //抓拍总次数
        int capturePhotoMaxNumber = examPlanInfo.getCapturePhotoMaxNumber();
        //查询已抓拍次数 photoResourceType 1： 考试过程抓拍
        int capturePhotoAlreadyNumber = examPhotoService.getExamPhotoByWhere(examineeArrange.getExamineeArrangeID(), 1).size();
        //剩余抓拍次数 = 总次数 - 已抓拍次数
        int capturePhotoResidueNumber = capturePhotoMaxNumber - capturePhotoAlreadyNumber;
        examInfoVo.setCapturePhotoResidueNumber(capturePhotoResidueNumber);
        examInfoVo.setExamSubjectId(subject.getExamSubjectID());
        examInfoVo.setExamineeArrangeId(examineeArrange.getExamineeArrangeID());
        examInfoVo.setLoginMode(examPlanInfo.getLoginMode());
        return examInfoVo;
    }


    /**
     * 更改当前考试状态和开考时间
     * @param appId
     * @param planId
     * @param subjectId
     * @param examineeId
     * @return
     */
    public void exExamStateAndTime(String appId, String planId, String subjectId, String examineeId){
        ExamingMonitor examingMonitors = examMoniterMapper.findExamingMonitorsFirstOrDefault(appId, planId, subjectId, examineeId);
        if (!examingMonitors.getSysState().equals(ExamManagerState.BeingNotSubmit.getPrefix().shortValue())){
            examingMonitors.setExamStartTime(DateUtil.convertDateToString(new Date()));
            examingMonitors.setSysState(ExamManagerState.BeingNotSubmit.getPrefix().shortValue());
            examMoniterMapper.updateExamingMoniter(examingMonitors);
        }
    }

    /**
     * 获取学生信息
     * @param token  key
     */
    public ExamineeInfoVo getExamineeInfo(String token) {
        //获取缓存数据
        ClientLoginModel clientLoginModel = getEhCacheValue(token);
        Examinee examinee = clientLoginModel.getExaminee();
        ExamineeArrange examineeArrange = clientLoginModel.getExamArrange();

        //返回Vo
        ExamineeInfoVo examineeInfoVo = new ExamineeInfoVo();
        examineeInfoVo.setExamineeName(examinee.getExamineeName());
        examineeInfoVo.setExamCardNo(examinee.getExamCardNo());
        examineeInfoVo.setCertificateType(examinee.getCertificateType());
        examineeInfoVo.setCertificateNo(examinee.getCertificateNo());
        examineeInfoVo.setSeatNo(examineeArrange.getSeatNo() == null ? 0 : examineeArrange.getSeatNo());
        examineeInfoVo.setExamRoomId(examineeArrange.getExamRoomID() == null ? "0" : examineeArrange.getExamRoomID());
        examineeInfoVo.setTypeName(CertificateType.getcertificateType(examinee.getCertificateType().intValue()));

        examineeInfoVo.setAppId(examinee.getAppID());
        examineeInfoVo.setPlanId(examineeArrange.getExamPlanInfoID());
        examineeInfoVo.setSubjectId(examineeArrange.getExamSubjectID());
        examineeInfoVo.setExamineeId(examineeArrange.getExamineeID());
        return examineeInfoVo;
    }

    /**
     * 获取前端显示JSON (清空正确答案、补充之前的作答)
     * @param token
     * @return
     */
    public Map<String, Object> getExamPaper(String token) {
        Map<String,Object> returnMap = new HashMap<>();
        //获取缓存数据
        ClientLoginModel clientLoginModel = getEhCacheValue(token);
        Examinee examinee = clientLoginModel.getExaminee();

        // 获取试卷
        TestPaperTemplate testPaper = examPaperService.getStudentPaper(token);
        String identifier = StringUtils.isEmpty(testPaper) ?  "" : testPaper.getIdentifier().toLowerCase();
        // 获取作答集合
        List<ExamineeAnswerDetailViewModel> examineeAnswerDetailViewModels = new ArrayList<>();
        List<Map<String, Object>> examineeAnswerDetails = examineeAnswerDetailMapper.findExamineeAnswerDetails(examinee.getExamineeID(), identifier);
        for (Map<String, Object> map:examineeAnswerDetails){
            ExamineeAnswerDetailViewModel examineeAnswerDetailViewModel = new ExamineeAnswerDetailViewModel();
            examineeAnswerDetailViewModel.setExamPaperID((String) map.get("ExamPaperID"));
            examineeAnswerDetailViewModel.setExamPaperItemId((String)map.get("ExamPaperItemId"));
            examineeAnswerDetailViewModel.setSequenceIndex((Integer)map.get("SequenceIndex"));
            examineeAnswerDetailViewModel.setIsCompletion((Integer)map.get("IsCompletion"));
            examineeAnswerDetailViewModel.setAnswerResults(GsonUtil.fromJsonToList((String)map.get("AnswerResults"),String.class));
            examineeAnswerDetailViewModel.setMarked((Boolean)map.get("IsMarked"));
            examineeAnswerDetailViewModels.add(examineeAnswerDetailViewModel);
        }

        returnMap.put("testpaper",testPaper);
        returnMap.put("answerDetails",examineeAnswerDetailViewModels);
        return returnMap;
    }

    /**
     * 获取缓存
     * @param token
     * @return
     */
    public ClientLoginModel getEhCacheValue(String token){
        //获取缓存数据
        Map<String,Object> info = null;
        if( PatternUtil.getPatternSplit(token,":").size() > 1){
            info =  GsonUtil.fromJsonToMap(RedisUtil.getValue(token));
            return  GsonUtil.fromJsonToObject(GsonUtil.toJson(info), ClientLoginModel.class);
        }else {
            //info = (Map) JSONObject.parse(ehCacheManager.get(token));
            //Map<String,Object> value = (Map)JSONObject.parse((String) info.get("value"));
            //return  GsonUtil.fromJsonToObject(GsonUtil.toJson(value), ClientLoginModel.class);
            return null;
        }
    }

    /**
     * 获取考试期间时间
     * @param token
     * @return
     */
    public ExamPeriodTimeVo getTime(String token) {

        //返回Vo
        ExamPeriodTimeVo examPeriodTimeVo = new ExamPeriodTimeVo();
        //获取缓存
        ClientLoginModel clientLoginModel = getEhCacheValue(token);
        Examinee examinee = clientLoginModel.getExaminee();
        ExamPlanInfo examPlanInfo = clientLoginModel.getExamPlan();
        ExamSubject subject = clientLoginModel.getExamSubject();
        ExamineeArrange examineeArrange = clientLoginModel.getExamArrange();

        String appId = examinee.getAppID();
        String examPlanInfoId = examineeArrange.getExamPlanInfoID();
        String examSubjectId = examineeArrange.getExamSubjectID();
        String examineeId = examinee.getExamineeID();

        ExamingMonitor examingMonitors = examMoniterMapper.findExamingMonitorsFirstOrDefault(appId, examPlanInfoId
                , examSubjectId, examineeId);
        //延迟时长
        Integer delayMinute = examingMonitors.getDelayMinute();
        // retainTime:     剩余时长（秒）
        Integer retainTime = examingService.saveExamineeRetainTime(examingMonitors,examPlanInfo,subject,examineeArrange);
        //examLength:     科目考试时长（秒）
        Integer examLength = subject.getTimeLimits() * 60 + delayMinute * 60 ;
        //timeToBegin:    距离考试开始时间（秒）
        Integer timeToBegin = DateUtil.getTimeDifference(DateUtil.convertStringToDate(examineeArrange.getPlanBeginTime()),new Date()).intValue();
        //最小考试时长（分）
        Integer minExamTime = examPlanInfo.getMinExamTime();

        // 如果考试计划为必考模式，且当前考试科目是必修课，则最小考试时长取科目时长
        if(ExamMode.unifiedExam.getPrefix().equals(examPlanInfo.getExamMode()) &&
                SubjectType.compulsory.getPrefix().equals(subject.getSubjectType().intValue())){
            minExamTime = subject.getTimeLimits();

        }else if (ExamPlanApplicationRange.Mock.getPrefix().equals(examPlanInfo.getExamPlanType().intValue())){
            // 如果是模拟考试，TimeTobegin 和 MinExamTime 赋值
            timeToBegin = 0;
            minExamTime = 0;
        }
        examPeriodTimeVo.setRetainTime(retainTime);
        examPeriodTimeVo.setExamLength(examLength);
        examPeriodTimeVo.setTimeToBegin(timeToBegin);
        examPeriodTimeVo.setMinExamTime(minExamTime);

        return examPeriodTimeVo;

    }


    /**
     * 保存整卷作答结果
     * 0 保存失败
     * 1 保存成功
     * 2 缓存丢失
     * 3 已被强制交卷
     * 4 已在其他考试机登录
     * 5 已交卷
     * @param token
     * @param answerList
     */
    public SaveAnswerVo saveAnswer(String token, List<ExamineeAnswerDetailViewModel> answerList,String hostAddress){
        ClientLoginModel clientLoginModel = getEhCacheValue(token);
        // 缓存丢失，未登录
        if (StringUtils.isEmpty(clientLoginModel)){
            return new SaveAnswerVo(SaveAnswerType.CACHE_LOST.getPrefix());
        }
        Examinee examinee = clientLoginModel.getExaminee();
        ExamineeArrange examineeArrange = clientLoginModel.getExamArrange();

        //是否已交卷
        ExamingMonitor examingMonitorsByIsSubmited = examMoniterMapper.findExamingMonitorsByIsSubmited(examineeArrange.getExamPlanInfoID(),
                examineeArrange.getExamSceneID(), examineeArrange.getExamRoomID(), examineeArrange.getExamSubjectID(), examinee.getExamineeID());
        if(examingMonitorsByIsSubmited.getSysState().equals(ExamManagerState.Submited.getPrefix().shortValue())){
            return new SaveAnswerVo(SaveAnswerType.PAPERS_HAVE_BEEN.getPrefix(),false,false);
        }

        OperationResult operationResult = examingService.saveAnswer(examinee.getExamineeID(), answerList);
        if (operationResult.getResultType() == OperationResultType.Success){
            return new SaveAnswerVo(SaveAnswerType.SAVE_SUCCESS.getPrefix(),false,false);
        }else {
            return new SaveAnswerVo(SaveAnswerType.SAVE_FAILED.getPrefix(),false,false);
        }
    }

    /**
     * 提交试卷，清空cache
     * @param token key
     * @param submitType 提交类型 交卷类型：0未交卷；1考生自行交卷；2考生试卷导入；3系统自动交卷；4强制交卷
     * @param isMandatory 是否是强制提交
     * @return
     */
    @Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class)
    public OperationResult submitPaper(String token, Integer submitType, boolean isMandatory){

        ClientLoginModel clientLoginModel = getEhCacheValue(token);
        Examinee examinee = clientLoginModel.getExaminee();
        ExamPlanInfo examPlanInfo = clientLoginModel.getExamPlan();
        ExamineeArrange examineeArrange = clientLoginModel.getExamArrange();

        String appId = examineeArrange.getAppID();
        String examPlanInfoId = examineeArrange.getExamPlanInfoID();
        String examSubjectId = examineeArrange.getExamSubjectID();
        String examineeId = examinee.getExamineeID();
        String examCardNo = examinee.getExamCardNo();
        Integer minExamTime = examPlanInfo.getMinExamTime();
        Integer examMode = examPlanInfo.getExamMode();

        //获取考试开始时间
        String startTime = null;
        ExamingMonitor examingMonitor = null;
        Object examStartTime = getExamStartTime(appId, examPlanInfoId, examMode, examSubjectId, examineeId);
        if(examStartTime instanceof ExamingMonitor){
            examingMonitor = (ExamingMonitor) examStartTime;
            startTime = examingMonitor.getExamStartTime();
        }else if(examStartTime instanceof ExamineeArrange){
            ExamineeArrange arrange = (ExamineeArrange) examStartTime;
            startTime = arrange.getPlanBeginTime();
        }

        // 如果不是强制交卷的情况，需要验证是否到了最小的交卷时间，未到不允许交卷
        if (!isMandatory
                && System.currentTimeMillis() < DateUtil.addOrDelDate(DateUtil.convertStringToDate(startTime),minExamTime).getTime()){
            return new OperationResult(OperationResultType.Warning,"交卷失败，未到最小交卷时间");
        }

        return examingService.submitPaper(examingMonitor,examMode,appId,examPlanInfoId,examSubjectId,examineeId,submitType);
    }

    /**
     * 获取考试开始时间（区分统考和随考）
     * @param appId  主办方标识
     * @param examPlanInfoId 计划标识
     * @param examMode  考试模式：1统考；2预考；3随考；4必考
     * @param examSubjectId  科目标识
     * @param examineeId  考生标识
     * @return
     */
    public Object getExamStartTime(String appId, String examPlanInfoId, Integer examMode, String examSubjectId, String examineeId) {
        if (ExamMode.unifiedExam.getPrefix().equals(examMode)) {
            // 统考取编排表开考时间
            return examineeArrangeMapper.findExamBeginTime(examineeId, examPlanInfoId, appId, examSubjectId);
        }else {
            // 随考取监控表开考时间
            return examMoniterMapper.findExamingMonitorsFirstOrDefault(appId, examPlanInfoId, examSubjectId, examineeId);
        }
    }


    /**
     * 保存考生照片
     * @param token
     * @param type 1：考试抓拍  2：登录拍照
     * @param data 图片的
     * 考试抓拍有次数限制。
     * 登录拍照只存一条数据，多次拍照修改源数据
     * @return
     */
    public OperationResult saveExamineePhoto(String token, Integer type, String data){

        //获取缓存
        ClientLoginModel ehCacheValue = getEhCacheValue(token);
        ExamPlanInfo examPlan = ehCacheValue.getExamPlan();
        ExamineeArrange examArrange = ehCacheValue.getExamArrange();
        Examinee examinee = ehCacheValue.getExaminee();
        //人脸比对图片获取路径
        String photoResource = examinee.getPhotoResource();

        //1,上传
        String rootPath = ExamSitePath.rootPath;
        String filePath = "";
        if(PhotoResourceType.FaceCompare.getPrefix().equals(type)){
            filePath =  "/"+examPlan.getExamPlanInfoID()+"/"+examPlan.getExamSiteID()+"/photos/"+examinee.getExamCardNo()+"_"+type+".jpg";
        }else if(PhotoResourceType.TestingCapture.getPrefix().equals(type) || PhotoResourceType.Scene.getPrefix().equals(type)){
            filePath =  "/"+examPlan.getExamPlanInfoID()+"/"+examPlan.getExamSiteID()+"/photos/"+examinee.getExamCardNo()+"_"+type+"_"+System.currentTimeMillis()+".jpg";
        }
        if(FileUtil.isFileExsit(rootPath+filePath)){
            FileUtil.deleteFile(rootPath+filePath);
        }
        FileUtil.writePhoto(rootPath+filePath,data);

        Double score = Double.valueOf(0);//人脸对比得分
        int faceCompareResult = 0; // 对比结果  0-false;1-true
        if( PatternUtil.getPatternSplit(token,":").size() > 1){
            //2，获取考生照片
            File sourceFile = new File(rootPath+filePath); //对比图
            File targetFile = new File(rootPath+photoResource); //用户认证图
            //3，照片比对
            score = faceCompareByFile.faceCompareByFile(sourceFile, targetFile);
            if(score.compareTo(faceCompareSocre == null ? 0D : faceCompareSocre) > 0){
                faceCompareResult = 1;
            }
        }

        //4,存储
        if(PhotoResourceType.FaceCompare.getPrefix().equals(type)){
            List<ExamPhoto> examPhotos = examPhotoService.getExamPhotoByWhere(examArrange.getExamineeArrangeID(), type);
            if(examPhotos.isEmpty()){
                ExamPhoto examPhoto = new ExamPhoto();
                examPhoto.setExamPhotoID(UUID.randomUUID().toString());
                examPhoto.setExamineeArrangeID(examArrange.getExamineeArrangeID());
                examPhoto.setPhotoResourceType(type);
                examPhoto.setPhotoResourcePath(filePath);
                examPhoto.setScore(score);
                examPhoto.setFaceCompareResult(faceCompareResult);//0-false;1-true
                examPhoto.setInsertTime(DateUtil.convertEncryptDateToString(new Date()));
                examPhotoService.saveExamineePhoto(examPhoto);
            }else {
                ExamPhoto examPhoto = examPhotos.get(0);
                examPhoto.setExamineeArrangeID(examArrange.getExamineeArrangeID());
                examPhoto.setPhotoResourceType(type);
                examPhoto.setPhotoResourcePath(filePath);
                examPhoto.setScore(score);
                examPhoto.setFaceCompareResult(faceCompareResult);//0-false;1-true
                examPhoto.setInsertTime(DateUtil.convertEncryptDateToString(new Date()));
                examPhotoService.updateExamineePhoto(examPhoto);
            }

        }else if(PhotoResourceType.TestingCapture.getPrefix().equals(type) || PhotoResourceType.Scene.getPrefix().equals(type)){
            ExamPhoto examPhoto = new ExamPhoto();
            examPhoto.setExamPhotoID(UUID.randomUUID().toString());
            examPhoto.setExamineeArrangeID(examArrange.getExamineeArrangeID());
            examPhoto.setPhotoResourceType(type);
            examPhoto.setPhotoResourcePath(filePath);
            examPhoto.setScore(score);
            examPhoto.setFaceCompareResult(faceCompareResult);//0-false;1-true
            examPhoto.setInsertTime(DateUtil.convertEncryptDateToString(new Date()));
            examPhotoService.saveExamineePhoto(examPhoto);
        }


        //5，返回结果
        return new OperationResult(OperationResultType.Success ,OperationResultType.Success.getDisplay(),faceCompareResult);
    }

    /**
     * 获取承诺书展示学生相关信息
     * @param token
     * @return
     */
    public PromiseExamineeInfoVo getPromiseExamineeInfo(String token) {
        PromiseExamineeInfoVo promiseExamineeInfoVo = new PromiseExamineeInfoVo();
        //获取缓存
        ClientLoginModel clientLoginModel = getEhCacheValue(token);
        Examinee examinee = clientLoginModel.getExaminee();
        ExamineeArrange examArrange = clientLoginModel.getExamArrange();

        promiseExamineeInfoVo.setStuName(examinee.getExamineeName());
        promiseExamineeInfoVo.setSex(examinee.getSex());
        promiseExamineeInfoVo.setExamCardNo(examinee.getExamCardNo());
        promiseExamineeInfoVo.setIdCard(examinee.getCertificateNo());
        promiseExamineeInfoVo.setCertificateType(examinee.getCertificateType());
        promiseExamineeInfoVo.setExaminerHeadPhotoUrl(examinee.getPhotoResource());
        promiseExamineeInfoVo.setLoginMode(clientLoginModel.getExamPlan().getLoginMode());

        //获取人脸识别最新图片
        List<ExamPhoto> examPhotoList = examPhotoService.getExamPhotoByWhere(examArrange.getExamineeArrangeID(),2);
        if(!examPhotoList.isEmpty()){
            ExamPhoto examPhoto = examPhotoList.get(0);
            promiseExamineeInfoVo.setFaceComparePhotoUrl(examPhoto.getPhotoResourcePath());
            promiseExamineeInfoVo.setScore(examPhoto.getScore() == null ? 0 : examPhoto.getScore());
        }else {
            promiseExamineeInfoVo.setFaceComparePhotoUrl("");
            promiseExamineeInfoVo.setScore(0D);
        }
        return promiseExamineeInfoVo;
    }

    /**
     * 获取人脸识别页所需信息
     * @param token
     * @return
     */
    public FaceCompareExamineeInfoVo getFaceCompareExamineeInfo(String token) {
        FaceCompareExamineeInfoVo faceCompareExamineeInfoVo = new FaceCompareExamineeInfoVo();
        //获取缓存
        ClientLoginModel clientLoginModel = getEhCacheValue(token);
        Examinee examinee = clientLoginModel.getExaminee();
        faceCompareExamineeInfoVo.setExaminerHeadPhotoUrl(examinee.getPhotoResource());
        faceCompareExamineeInfoVo.setStuName(examinee.getExamineeName());
        return faceCompareExamineeInfoVo;
    }


    public static void main(String[] args) {
        Double s = 68.7;
        System.out.println(s.compareTo(65D));
    }
}
